/*===========================================================================
  Copyright (C) 2012-2013 by the Okapi Framework contributors
-----------------------------------------------------------------------------
  This library is free software; you can redistribute it and/or modify it 
  under the terms of the GNU Lesser General Public License as published by 
  the Free Software Foundation; either version 2.1 of the License, or (at 
  your option) any later version.

  This library is distributed in the hope that it will be useful, but 
  WITHOUT ANY WARRANTY; without even the implied warranty of 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
  General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License 
  along with this library; if not, write to the Free Software Foundation, 
  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

  See also the full LGPL text here: http://www.gnu.org/copyleft/lesser.html
===========================================================================*/

package net.sf.okapi.applications.lynx;

import java.io.File;
import java.io.PrintWriter;
import java.util.List;
import java.util.Stack;

import net.sf.okapi.lib.xliff2.Const;
import net.sf.okapi.lib.xliff2.Util;
import net.sf.okapi.lib.xliff2.core.MTag;
import net.sf.okapi.lib.xliff2.core.CTag;
import net.sf.okapi.lib.xliff2.core.StartXliffData;
import net.sf.okapi.lib.xliff2.core.Fragment;
import net.sf.okapi.lib.xliff2.core.Part;
import net.sf.okapi.lib.xliff2.core.StartFileData;
import net.sf.okapi.lib.xliff2.core.StartGroupData;
import net.sf.okapi.lib.xliff2.core.TagType;
import net.sf.okapi.lib.xliff2.core.Unit;
import net.sf.okapi.lib.xliff2.reader.Event;
import net.sf.okapi.lib.xliff2.reader.XLIFFReader;

public class HtmlPreview {

	private PrintWriter writer;

	private final String START_TRANS = "<span style='color:black'>";
	private final String START_NOTRANS = "<span style='color:red'>";
	private final String ENDING = "</span>";
	
	public void process (List<File> list) {
		// Else: process the input files
		XLIFFReader reader = new XLIFFReader(XLIFFReader.VALIDATION_MAXIMAL);
		writer = null;
		Stack<String> elems = new Stack<String>();
		try {
			File output = null;
			for ( File input : list ) {
				// Show the input path
				System.out.println(" Input: "+input.getAbsolutePath());

				// Compute the output path
				String path = input.getAbsolutePath();
				output = new File(path+".html");
				System.out.println("Output: "+output.getAbsolutePath());
				
				// Open the input and create the output
				reader.open(input.toURI());
				writer = new PrintWriter(output);
				String fs;
				
				while ( reader.hasNext() ) {
					// Get the event
					Event event = reader.next();
					
					// Display the trace
					switch ( event.getType() ) {
					case START_XLIFF:
						StartXliffData dd = event.getStartXliffData();
						fs = dd.getExtAttributeValue(Const.NS_XLIFF_FS20, "fs");
						if ( fs == null ) fs = "html";
						writer.print("<"+fs+">"); elems.push(fs);
						break;
						
					case START_FILE:
						StartFileData sfd = event.getStartFileData();
						fs = sfd.getExtAttributeValue(Const.NS_XLIFF_FS20, "fs");
						if ( fs == null ) fs = "hr";
						writer.print("<"+fs+">"); elems.push(fs);
						break;
						
					case START_GROUP:
						StartGroupData sgd = event.getStartGroupData();
						fs = sgd.getExtAttributeValue(Const.NS_XLIFF_FS20, "fs");
						if ( fs == null ) fs = "div";
						writer.print("<"+fs+">"); elems.push(fs);
						break;
						
					case TEXT_UNIT:
						Unit unit = event.getUnit();
						fs = unit.getExtAttributeValue(Const.NS_XLIFF_FS20, "fs");
						if ( fs == null ) fs = "p";
						writer.print("<"+fs+">"); elems.push(fs);
						
						Stack<Boolean> trans = new Stack<Boolean>();
						List<Part> trgOrderedParts = unit.getTargetOrderedParts();
						List<Boolean> endings = unit.getTranslateStateEndings(false);
						// Get the default for the first part
						boolean initialTranslate = unit.getTranslate();
						for ( int i=0; i<trgOrderedParts.size(); i++ ) {
							printPart(trgOrderedParts.get(i),
								(i==0 ? initialTranslate : endings.get(i-1)),
								trans);
						}
						break;
						
					case END_GROUP:
						writer.println("</"+elems.pop()+">");
						break;
						
					case END_FILE:
						writer.println("</"+elems.pop()+">");
						break;
						
					case END_XLIFF:
						writer.println("</"+elems.pop()+">");
						break;
						
					case END_DOCUMENT:
					case INSIGNIFICANT_PART:
					case SKELETON:
					case START_DOCUMENT:
					case MID_FILE:
						break;
					}
				}
			}
		}
		catch ( Throwable e ) {
			System.out.println("Error while generating HTML: "+e.getMessage());
		}
		finally {
			if ( reader != null ) {
				reader.close();
			}
			if ( writer != null ) {
				writer.close();
			}
		}
	}

	private void printPart (Part part,
		boolean translateStartContext,
		Stack<Boolean> trans)
	{
		if ( part.hasTarget() ) printFragment(part.getTarget(), translateStartContext, trans);
		else printFragment(part.getSource(), translateStartContext, trans);
	}

	private void printFragment (Fragment frag,
		boolean translateStartContext,
		Stack<Boolean> trans)
	{
		if ( translateStartContext ) writer.print(START_TRANS);
		else writer.print(START_NOTRANS);

		String tmp;
		for ( Object obj : frag ) {
			if ( obj instanceof String ) {
				writer.print(Util.toXML((String)obj, false));
			}
			else if ( obj instanceof CTag ) {
				CTag cm = (CTag)obj;
				tmp = cm.getDisp();
				if ( tmp == null ) {
					if ( cm.getTagType() == TagType.OPENING ) tmp = "<u>";
					else if ( cm.getTagType() == TagType.CLOSING ) tmp = "</u>";
					else tmp = "";
				}
				else tmp = Util.toXML(tmp, false);
				writer.print(tmp);
			}
			else { // Must be AMarker
				MTag am = (MTag)obj;
				if ( am.getTagType() == TagType.OPENING ) {
					if ( am.getTranslate() != null ) {
						if ( am.getTranslate() ) {
							trans.push(true);
							writer.print(START_TRANS);
						}
						else { 
							trans.push(false);
							writer.print(START_NOTRANS);
						}
					}
					tmp = "<span title=\""+Util.toXML(am.getType(), true)+"\">";
				}
				else {
					tmp = "</span>";
					if ( am.getTranslate() != null ) {
						tmp += ENDING;
						trans.pop();
					}
				}
				writer.print(tmp);
			}
		}
		writer.println("</span>");
	}

}
